package com.loveprogrammer.eternity.action;

import com.loveprogrammer.eternity.common.Constants;
import com.loveprogrammer.eternity.enums.ConsoleColors;
import com.loveprogrammer.eternity.enums.QualityEnum;
import com.loveprogrammer.eternity.factory.*;
import com.loveprogrammer.eternity.factory.template.MapTemplate;
import com.loveprogrammer.eternity.model.Character;
import com.loveprogrammer.eternity.model.Hero;
import com.loveprogrammer.eternity.model.Monster;
import com.loveprogrammer.eternity.model.console.ConsolePrint;
import com.loveprogrammer.eternity.model.game.GameWrapper;
import com.loveprogrammer.eternity.model.game.HeroWrapper;
import com.loveprogrammer.eternity.model.game.PetWrapper;
import com.loveprogrammer.eternity.model.map.Map;
import com.loveprogrammer.eternity.model.npc.NPC;
import com.loveprogrammer.eternity.model.product.*;
import com.loveprogrammer.eternity.model.product.eggs.Egg;
import com.loveprogrammer.eternity.model.product.equipment.Equips;
import com.loveprogrammer.eternity.service.CasinoService;
import com.loveprogrammer.eternity.utils.BeanCopyUtils;
import com.loveprogrammer.eternity.utils.LoadGame;
import com.loveprogrammer.eternity.utils.ScannerInput;
import io.netty.util.HashedWheelTimer;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * @version 1.0.0
 * @description:
 * @author: eric
 * @date: 2022-08-04 10:25
 **/
public class SimpleStart extends BaseAction {

    private GameWrapper gameWrapper;

    private AtomicBoolean quit = new AtomicBoolean(false);

    public void start(HeroWrapper heroWrapper, GameWrapper gameWrapper) throws Exception {
        this.gameWrapper = gameWrapper;
        // 不是直接打，要增加操作项目
        eventManager.notifyMessage("请选择您要进行的操作", 1);
        eventManager.notifyMessage("【1.打怪】  【2.装备】  【3.战兽】", 1);
        eventManager.notifyMessage("【4.冒险者工会】   【5.副本】  【6.伙伴】 ", 1);
        eventManager.notifyMessage("【8.配置】  【9.退出】", 1);
        eventManager.notifyPrompt("请选择：");
        int choose = ScannerInput.inputInt(1, 9, 9);
        while (choose != 9) {
            switch (choose) {
                case 1:
                    autoFight(heroWrapper,gameWrapper);
                    break;
                case 2:
                    checkAndChangeEquipment(heroWrapper);
                    break;
                case 3:
                    petsAndEggs(heroWrapper);
                    break;
                case 4:
                    adventurersGuild(heroWrapper);
                    break;
                case 5:
                    eventManager.notifyMessage("暂未开放，敬请期待", 1);
                    break;
                case 6:
                    partner(heroWrapper);
                    break;
                case 7:
                    eventManager.notifyMessage("暂未开放，敬请期待", 1);
                    break;
                case 8:
                    eventManager.notifyMessage("暂未开放，敬请期待", 1);
                    break;
                default:
                    break;
            }

            eventManager.notifyMessage("请选择您要进行的操作", 1);
            eventManager.notifyMessage("【1.打怪】  【2.装备】  【3.战兽】", 1);
            eventManager.notifyMessage("【4.冒险者工会】   【5.副本】  【6.伙伴】 ", 1);
            eventManager.notifyMessage("【8.配置】  【9.退出】", 1);
            eventManager.notifyPrompt("请选择：");
            choose = ScannerInput.inputInt(1, 9, 9);
        }
        LoadGame.save(gameWrapper);
        eventManager.notifyMessage("bye", 1);
    }

    private void petsAndEggs(HeroWrapper heroWrapper) {
        //
        eventManager.notifyMessage("你好冒险者，你需要的服务是：", 1);
        eventManager.notifyMessage("【1.孵化宠物】 \n【2.检查并更换出战宠物】 \n【0.返回】", 1);
        eventManager.notifyPrompt("请选择：");
        int choose = ScannerInput.inputInt(1, 2, 0);
        while (choose != 0) {
            switch (choose) {
                case 1:
                    checkEggs(heroWrapper);
                    break;
                case 2:
                    checkAndChangePets(heroWrapper);
                    break;
                default:
                    break;
            }
            eventManager.notifyMessage("你好冒险者，你需要的服务是：", 1);
            eventManager.notifyMessage("【1.孵化宠物】 \n【2.检查并更换出战宠物】 \n【0.返回】", 1);
            eventManager.notifyPrompt("请选择：");
            choose = ScannerInput.inputInt(1, 2, 0);
        }
        LoadGame.save(gameWrapper);
    }

    private void partner(HeroWrapper heroWrapper) {
        eventManager.notifyMessage("尚未开启", 1);
    }

    private void casino(HeroWrapper heroWrapper) {
        // 赌场
        CasinoService.gamble(heroWrapper);
    }

    private void adventurersGuild(HeroWrapper heroWrapper) throws IOException, ClassNotFoundException {
        //
        eventManager.notifyMessage("你好冒险者，你需要的服务是：", 1);
        eventManager.notifyMessage("【1.商店】 【2.赌场】 【3.转职】 【4.返回】", 1);
        eventManager.notifyPrompt("请选择：");
        int choose = ScannerInput.inputInt(1, 4, 4);
        while (choose != 4) {
            switch (choose) {
                case 1:
                    store(heroWrapper);
                    break;
                case 2:
                    casino(heroWrapper);
                    break;
                case 3:
                    transfer(heroWrapper);
                    break;
                default:
                    break;
            }
            eventManager.notifyMessage("你好冒险者，你需要的服务是：", 1);
            eventManager.notifyMessage("【1.商店】 【2.赌场】 【3.转职】 【4.返回】", 1);
            eventManager.notifyPrompt("请选择：");
            choose = ScannerInput.inputInt(1, 4, 4);
        }
        LoadGame.save(gameWrapper);
    }

    // 转职
    private void transfer(HeroWrapper heroWrapper) throws IOException, ClassNotFoundException {
        JobFactory.transfer(heroWrapper);
    }

    private void store(HeroWrapper heroWrapper) {
        //
        eventManager.notifyMessage("欢迎来到商店，请问您要进行的操作：", 1);
        eventManager.notifyMessage("【1.买东西】 【2.卖东西】 【3.拍卖行】 【4.返回】", 1);
        eventManager.notifyPrompt("请选择：");
        int choose = ScannerInput.inputInt(1, 4, 4);
        while (choose != 4) {
            switch (choose) {
                case 1:
                    buy(heroWrapper);
                    break;
                case 2:
                    sale(heroWrapper);
                    break;
                case 3:
                    auctionHouse(heroWrapper);
                    break;
                default:
                    break;
            }
            eventManager.notifyMessage("欢迎来到商店，请问您要进行的操作：", 1);
            eventManager.notifyMessage("【1.买东西】 【2.卖东西】 【3.拍卖行】 【4.返回】", 1);
            eventManager.notifyPrompt("请选择：");
            choose = ScannerInput.inputInt(1, 4, 4);
        }
        LoadGame.save(gameWrapper);
    }

    private void buy(HeroWrapper heroWrapper) {
        // 列出商店的货物 商店的货物随机产生 价格是卖出价格的两倍
        List<Goods> saleGoods = StoreFactory.getSaleGoods();
        for (int i = 0; i < saleGoods.size(); i++) {
            eventManager.notifyMessage((i + 1) + saleGoods.get(i).toString() + "\t" + "售价" + saleGoods.get(i).price().showPrice(), 1);
        }
        eventManager.notifyMessage("输入数字来购买，输入0返回", 1);

        int choose = ScannerInput.inputInt(1, saleGoods.size(), 0);
        if (choose != 0) {
            boolean buy = heroWrapper.buy(saleGoods.get(choose - 1));
            if (!buy) {
                eventManager.notifyMessage("对不起您的钱不够", 1);
            } else {
                eventManager.notifyMessage("购买成功", 1);
            }
        }
    }

    private void sale(HeroWrapper heroWrapper) {
        eventManager.notifyMessage("欢迎来到商店，请问您要进行的操作：", 1);
        eventManager.notifyMessage("【1.卖掉所有装备（不包含已穿戴的）】", 1);
        eventManager.notifyMessage("【2.卖掉所有未孵化的宠物卵（保留帝王和君主级别宠物卵）】", 1);
        eventManager.notifyMessage("【3.卖掉所有未孵化的宠物卵】", 1);
        eventManager.notifyMessage("【4.返回】", 1);
        eventManager.notifyPrompt("请选择：");
        int choose = ScannerInput.inputInt(1, 4, 4);

        switch (choose) {
            case 1:
                saleEquipments(heroWrapper);
                break;
            case 2:
                saleEggs(heroWrapper, true);
                break;
            case 3:
                saleEggs(heroWrapper, false);
                break;
            default:
                break;
        }

    }

    private void auctionHouse(HeroWrapper heroWrapper) {
        eventManager.notifyMessage("现有业务", 1);
        eventManager.notifyMessage("1、银币兑换金币", 1);
        eventManager.notifyMessage("2、金币兑换钻石", 1);
        eventManager.notifyMessage("9、返回", 1);
        eventManager.notifyPrompt("请选择：");
    }

    private void checkEggs(HeroWrapper heroWrapper) {
        //
        eventManager.notifyMessage("您目前拥有的宠物卵如下：", 1);
        List<Egg> eggs = heroWrapper.getWarehouse().getEggs();
        Collections.sort(eggs);
        if (eggs.size() > 0) {
            for (int i = 0; i < eggs.size(); i++) {
                eventManager.notifyMessage((i + 1) + ":" + eggs.get(i).prettyPrint(), 1);
            }

            eventManager.notifyMessage("请选择您要孵化的宠物卵 输入-1表示全部孵化 -2表示全部孵化（仅保留传奇）, 0 退出", 1);
            eventManager.notifyPrompt("请选择：");
            int choose = ScannerInput.inputInt(-2, eggs.size(), 0);
            while (choose != 0 && choose < eggs.size() + 1) {
                if (choose == -1) {
                    for (Goods egg : eggs) {
                        Egg e = (Egg) egg;
                        Monster hatch = e.hatch();
                        hatch.setName(heroWrapper.getAliasName() + "的" + hatch.getName());
                        eventManager.notifyMessage("孵化宠物" + hatch.prettyPrint(), 1);
                        PetWrapper petWrapper = new PetWrapper(hatch);
                        heroWrapper.getPets().add(petWrapper);
                    }
                    heroWrapper.getWarehouse().setEggs(new ArrayList<>());
                    break;
                }
                if (choose == -2) {
                    for (Goods egg : eggs) {
                        Egg e = (Egg) egg;
                        Monster hatch = e.hatch();
                        if (hatch.getQualityEnum().equals(QualityEnum.红色)) {
                            hatch.setName(heroWrapper.getAliasName() + "的" + hatch.getName());
                            eventManager.notifyMessage("孵化宠物" + hatch.prettyPrint(), 1);
                            PetWrapper petWrapper = new PetWrapper(hatch);
                            heroWrapper.getPets().add(petWrapper);
                        }
                    }
                    heroWrapper.getWarehouse().setEggs(new ArrayList<>());
                    break;
                } else {
                    Egg egg = eggs.get(choose - 1);
                    Monster hatch = egg.hatch();
                    hatch.setName(heroWrapper.getAliasName() + "的" + hatch.getName());
                    eventManager.notifyMessage("孵化宠物" + hatch.prettyPrint(), 1);
                    PetWrapper petWrapper = new PetWrapper(hatch);
                    heroWrapper.getPets().add(petWrapper);
                    eggs.remove(eggs.get(choose - 1));

                    for (int i = 0; i < eggs.size(); i++) {
                        eventManager.notifyMessage((i + 1) + ":" + eggs.get(i).prettyPrint(), 1);
                    }
                    eventManager.notifyMessage("请选择您要孵化的宠物卵 输入-1表示全部孵化, 0 退出", 1);
                    eventManager.notifyPrompt("请选择：");
                    choose = ScannerInput.inputInt(-1, eggs.size(), 0);
                }
            }
        } else {
            eventManager.notifyMessage("无", 1);
        }
        LoadGame.save(gameWrapper);
    }

    private void checkAndChangePets(HeroWrapper heroWrapper) {
        eventManager.notifyMessage("您目前宠物如下：", 1);
        List<PetWrapper> pets = heroWrapper.getPets();
        Collections.sort(pets);
        for (int i = 0; i < pets.size(); i++) {
            eventManager.notifyMessage((i + 1) + ":" + pets.get(i).getPet().toString()
                    + (pets.get(i).getUsed() ? "已出战" : "未出战"), 1);
        }
        eventManager.notifyMessage("请选择操作：", 1);
        eventManager.notifyMessage("【1.卖掉宠物】    【2.修改出战状态】    【0.返回】", 1);
        eventManager.notifyPrompt("请选择：");
        int choose = ScannerInput.inputInt(1, 2, 0);
        if (choose == 0) {
            return;
        }
        if (choose == 1) {
            try {
                salePets(pets, heroWrapper);
            } catch (Exception e) {
                e.printStackTrace();
            }
            LoadGame.save(gameWrapper);
            checkAndChangePets(heroWrapper);
        } else {
            eventManager.notifyMessage("请选择对应的宠物切换出战状态，当前出战 " + heroWrapper.getFightPets().size() + " 个战宠，输入0 返回", 1);
            choose = ScannerInput.inputInt(1, pets.size(), 0);
            while (choose != 0) {
                List<Monster> fightPets = heroWrapper.getFightPets();
                PetWrapper petWrapper = pets.get(choose - 1);
                if (petWrapper.getUsed()) {
                    fightPets.remove(petWrapper.getPet());
                    eventManager.notifyMessage(petWrapper.getPet().getName() + "移除出战队列", 1);
                    petWrapper.setUsed(false);
                } else {
                    if (fightPets.size() >= 5) {
                        eventManager.notifyMessage("只能出战5个战宠", 1);
                    } else {
                        fightPets.add(petWrapper.getPet());
                        eventManager.notifyMessage(petWrapper.getPet().getName() + "进入战斗队列", 1);
                        petWrapper.setUsed(true);
                    }
                }
                for (int i = 0; i < pets.size(); i++) {
                    eventManager.notifyMessage((i + 1) + ":" + pets.get(i).getPet().toString()
                            + (pets.get(i).getUsed() ? "已出战" : "未出战"), 1);
                }
                eventManager.notifyMessage("请选择对应的宠物切换出战状态，当前出战 " + heroWrapper.getFightPets().size() + " 个战宠，输入0 返回", 1);
                choose = ScannerInput.inputInt(1, pets.size(), 0);
            }
            LoadGame.save(gameWrapper);
            checkAndChangePets(heroWrapper);
        }
    }

    private void salePets(List<PetWrapper> pets, HeroWrapper heroWrapper) {
        java.util.Map<Integer, PetWrapper> petMap = new HashMap<>();
        for (int i = 0; i < pets.size(); i++) {
            petMap.put(i + 1, pets.get(i));
        }
        eventManager.notifyMessage("请选择要卖掉的宠物序号(输入q退出）： 多个请求逗号隔开，跨度请用-，如 1,2-4,6 就是删除1、2、4、6", 1);
        eventManager.notifyPrompt("请选择要卖掉的宠物：");
        Scanner input = new Scanner(System.in);
        String command = input.nextLine();
        if (command != null && !"0".equals(command) && !"q".equals(command) && !"".equals(command)) {
            String[] split = command.split(",");
            for (String str : split) {
                if (str.contains("-")) {
                    String[] strings = str.split("-");
                    int min = Integer.parseInt(strings[0].trim());
                    if(min < 1){
                        min = 1;
                    }
                    int max = Math.min(Integer.parseInt(strings[1].trim()),pets.size()-1);

                    for (int index = min; index <= max; index++) {
                        // 卖掉
                        PetWrapper petWrapper = petMap.get(index);
                        if(heroWrapper.getFightPets().contains(petWrapper.getPet())){
                            ConsolePrint.publishMessage("对不起，不能删除已经出战的宠物");
                            continue;
                        }

                        Coin sale = petWrapper.getPet().sale();
                        heroWrapper.pickUp(null, sale);
                        pets.remove(petWrapper);
                    }
                } else {
                    int petId = Integer.parseInt(str.trim());
                    if (petId > 0) {
                        // 卖掉
                        PetWrapper petWrapper = petMap.get(petId);
                        if(heroWrapper.getFightPets().contains(petWrapper.getPet())){
                            ConsolePrint.publishMessage("对不起，不能删除已经出战的宠物");
                            continue;
                        }
                        Coin sale = petWrapper.getPet().sale();
                        heroWrapper.pickUp(null, sale);
                        pets.remove(petWrapper);
                    }
                }
            }
            heroWrapper.setPets(pets);
        }
    }

    private void checkAndChangeEquipment(HeroWrapper heroWrapper) {
        heroWrapper.resetThings();
        Hero hero = heroWrapper.getHero();
        //
        eventManager.notifyMessage("您目前穿戴的装备如下：", 1);
        Equips equips = hero.getEquips();
        if (equips != null) {
            eventManager.notifyMessage(equips.prettyPrint(), 1);
            if (equips.getSuitEffects() != null && equips.getSuitEffects().size() > 0) {
                eventManager.notifyMessage("您目前套装效果如下：", 1);
                for (WearSuitEffect suitEffect : equips.getSuitEffects()) {
                    eventManager.notifyMessage(suitEffect.toString(), 1);
                }
            }
            // 特殊效果

        } else {
            eventManager.notifyMessage("无装备：", 1);
        }
        //
        eventManager.notifyMessage("您选择操作：", 1);
        eventManager.notifyMessage("【1.根据系统推荐更换装备】  【2.查看已有装备,自选装备更换】 【3.卖掉装备】", 1);
        eventManager.notifyMessage("【4.合成装备（未开放）】   【5.查看共享装备】  【6.返回】", 1);
        eventManager.notifyPrompt("请选择：");
        int choose = ScannerInput.inputInt(1, 6, 6);
        while (choose != 6) {
            switch (choose) {
                case 1:
                    eventManager.notifyMessage("还没有那么智能", 1);
                    break;
                case 2:
                    searchAndWearEquipments(heroWrapper);
                    break;
                case 3:
                    saleEquipments(heroWrapper);
                    break;
                case 4:
                    eventManager.notifyMessage("合成功能暂不开放", 1);
                    break;
                case 5:
                    showAndWearCommonEquipments(heroWrapper);
                    break;
                default:
                    break;
            }

            eventManager.notifyMessage("您选择操作：", 1);
            eventManager.notifyMessage("【1.根据系统推荐更换装备】  【2.查看已有装备,自选装备更换】 【3.卖掉装备】", 1);
            eventManager.notifyMessage("【4.合成装备（未开放）】   【5.查看共享装备】  【6.返回】", 1);
            eventManager.notifyPrompt("请选择：");
            choose = ScannerInput.inputInt(1, 6, 6);
        }
        LoadGame.save(gameWrapper);
    }

    private void showAndWearCommonEquipments(HeroWrapper heroWrapper) {
        List<Equipment> equipmentList = CommonEquipmentFactory.getCommonEquipments();
        java.util.Map<QualityEnum, List<Equipment>> qualityEnumListMap = equipmentList.stream().collect(Collectors.groupingBy(Equipment::getQuality));
        eventManager.notifyMessage("您想看哪个品质的装备（将按照级别排序）：", 1);
        eventManager.notifyMessage("【1.普通】 【2.进阶】 【3.优质】 【4.卓越】 【5.传奇】 【6.史诗】 【7.套装】 【8.全部】 【9.退出】", 1);
        eventManager.notifyPrompt("请选择：");
        int choose = ScannerInput.inputInt(1, 9, 9);
        while (choose != 9) {
            switch (choose) {
                case 1:
                    showEquipments(qualityEnumListMap, QualityEnum.白色, heroWrapper, false, true);
                    break;
                case 2:
                    showEquipments(qualityEnumListMap, QualityEnum.蓝色, heroWrapper, false, true);
                    break;
                case 3:
                    showEquipments(qualityEnumListMap, QualityEnum.黄色, heroWrapper, false, true);
                    break;
                case 4:
                    showEquipments(qualityEnumListMap, QualityEnum.紫色, heroWrapper, false, true);
                    break;
                case 5:
                    showEquipments(qualityEnumListMap, QualityEnum.红色, heroWrapper, false, true);
                    break;
                case 6:
                    showEquipments(qualityEnumListMap, QualityEnum.暗金, heroWrapper, false, true);
                    break;
                case 7:
                    showEquipments(qualityEnumListMap, QualityEnum.绿色, heroWrapper, false, true);
                    break;
                case 8:
                    showEquipments(qualityEnumListMap, null, heroWrapper, false, true);
                    break;
                default:
                    break;
            }

            eventManager.notifyMessage("您想看哪个品质的装备（将按照级别排序）：", 1);
            eventManager.notifyMessage("【1.普通】 【2.进阶】 【3.优质】 【4.卓越】 【5.传奇】 【6.史诗】 【7.套装】 【8.全部】 【9.退出】", 1);
            eventManager.notifyPrompt("请选择：");
            choose = ScannerInput.inputInt(1, 9, 9);
        }
    }

    private void searchAndWearEquipments(HeroWrapper wrapper) {
        List<Equipment> equipmentList = wrapper.getWarehouse().getEquipmentList();
        java.util.Map<QualityEnum, List<Equipment>> qualityEnumListMap = equipmentList.stream().collect(Collectors.groupingBy(Equipment::getQuality));
        eventManager.notifyMessage("您想看哪个品质的装备（将按照级别排序）：", 1);
        eventManager.notifyMessage("【1.普通】 【2.进阶】 【3.优质】 【4.卓越】 【5.传奇】 【6.史诗】 【7.套装】 【8.全部】 【9.退出】", 1);
        eventManager.notifyPrompt("请选择：");
        int choose = ScannerInput.inputInt(1, 9, 9);
        while (choose != 9) {
            switch (choose) {
                case 1:
                    showEquipments(qualityEnumListMap, QualityEnum.白色, wrapper, true, false);
                    break;
                case 2:
                    showEquipments(qualityEnumListMap, QualityEnum.蓝色, wrapper, true, false);
                    break;
                case 3:
                    showEquipments(qualityEnumListMap, QualityEnum.黄色, wrapper, true, false);
                    break;
                case 4:
                    showEquipments(qualityEnumListMap, QualityEnum.紫色, wrapper, true, false);
                    break;
                case 5:
                    showEquipments(qualityEnumListMap, QualityEnum.红色, wrapper, false, false);
                    break;
                case 6:
                    showEquipments(qualityEnumListMap, QualityEnum.暗金, wrapper, false, false);
                    break;
                case 7:
                    showEquipments(qualityEnumListMap, QualityEnum.绿色, wrapper, false, false);
                    break;
                case 8:
                    showEquipments(qualityEnumListMap, null, wrapper, false, false);
                    break;
                default:
                    break;
            }

            eventManager.notifyMessage("您想看哪个品质的装备（将按照级别排序）：", 1);
            eventManager.notifyMessage("【1.普通】 【2.进阶】 【3.优质】 【4.卓越】 【5.传奇】 【6.史诗】 【7.套装】 【8.全部】 【9.退出】", 1);
            eventManager.notifyPrompt("请选择：");
            choose = ScannerInput.inputInt(1, 9, 9);
        }
    }

    private void showEquipments(java.util.Map<QualityEnum, List<Equipment>> qualityEnumListMap,
                                QualityEnum qualityEnum, HeroWrapper heroWrapper, boolean filter, boolean common) {
        Hero hero = heroWrapper.getHero();
        List<Equipment> show = new ArrayList<>();
        if (qualityEnum == null) {
            for (List<Equipment> equipment : qualityEnumListMap.values()) {
                show.addAll(equipment);
            }
        } else {
            List<Equipment> list = qualityEnumListMap.get(qualityEnum);
            if (list != null) {
                show.addAll(list);
            }
        }
        if (show.isEmpty()) {
            eventManager.notifyMessage("没有找到装备", 1);
            return;
        }
        // 要去掉自身装备的


        // 后面再分页
        for (int i = 0; i < show.size(); i++) {
            Equipment equipment = show.get(i);
            Equipment position = hero.getEquips().findByPosition(equipment.getEquipmentPosition());
            int score = 0;
            if (position != null) {
                score = position.score(hero);
            }
            equipment.setDifference(equipment.score(hero) - score);
        }
        if (filter) {
            show = show.stream().filter(e -> e.getDifference() > 0)
                    .sorted(Comparator.comparing(Equipment::getDifference).reversed())
                    .collect(Collectors.toList());
        } else {
            show = show.stream().sorted(Comparator.comparing(Equipment::getDifference).reversed())
                    .collect(Collectors.toList());
        }
        if (show.isEmpty()) {
            eventManager.notifyMessage("没有找到比当前更优秀的装备，默认隐藏属性更低的装备", 1);
            return;
        }

        for (int i = 0; i < show.size(); i++) {
            Equipment equipment = show.get(i);
            Equipment position = hero.getEquips().findByPosition(equipment.getEquipmentPosition());
            int difference = equipment.getDifference();
            eventManager.notifyMessage((i + 1) + ": " + equipment.showDifference(position, hero) + "\t "
                    + "  总评（ " + (difference > 0 ? (ConsoleColors.GREEN_BRIGHT + difference + ConsoleColors.RESET) : (ConsoleColors.RED + difference + ConsoleColors.RESET)) + ")", 1);
        }

        int choose;
        eventManager.notifyMessage("请选择序号-操作对应的装备 输入0 返回", 1);
        eventManager.notifyPrompt("请选择：");
        while (true) {
            choose = ScannerInput.inputInt(1, show.size(), 0);
            if (choose == 0) {
                break;
            }
            if (common) {
                eventManager.notifyMessage("请选择操作 1 穿上装备 2 移入私有背包 0 返回", 1);
                int oper = ScannerInput.inputInt(1, 2, 0);
                if (oper == 1) {
                    CommonEquipmentFactory.wearCommonEquipment(show.get(choose - 1), heroWrapper);
                } else if (oper == 2) {
                    CommonEquipmentFactory.obtainCommonEquipment(show.get(choose - 1), heroWrapper);
                }
                show.remove(show.get(choose - 1));
            } else {
                eventManager.notifyMessage("请选择操作 "
                        + ConsoleColors.RED_BOLD + " 1 穿上装备  "
                        + ConsoleColors.BLUE_BOLD + "2 放入宝箱(其他角色可见) "
                        + ConsoleColors.PURPLE_BOLD + " 3 锁定(无法卖出）"
                        + ConsoleColors.YELLOW_BOLD + " 4 解锁 " + ConsoleColors.RESET + " 输入0 返回", 1);
                int oper = ScannerInput.inputInt(1, 4, 0);
                if (oper == 1) {
                    String takeOffId = hero.wear(show.get(choose - 1), hero.getTemplate().getWeaponType());
                    heroWrapper.takeOff(takeOffId);
                } else if (oper == 2) {
                    CommonEquipmentFactory.addCommonEquipment(show.get(choose - 1), heroWrapper);
                    show.remove(show.get(choose - 1));
                } else if (oper == 3) {
                    eventManager.notifyMessage("未开放功能", 1);
                } else {
                    // 解锁
                    eventManager.notifyMessage("未开放功能", 1);
                }
            }
            if (show.isEmpty()) {
                eventManager.notifyMessage("没有装备", 1);
                break;
            }
            // 重新计算分值
            for (int i = 0; i < show.size(); i++) {
                Equipment equipment = show.get(i);
                Equipment position = hero.getEquips().findByPosition(equipment.getEquipmentPosition());
                int score = 0;
                if (position != null) {
                    score = position.score(hero);
                }
                equipment.setDifference(equipment.score(hero) - score);
            }
            if (filter) {
                show = show.stream().filter(e -> e.getDifference() > 0)
                        .sorted(Comparator.comparing(Equipment::getDifference).reversed())
                        .collect(Collectors.toList());
            } else {
                show = show.stream().sorted(Comparator.comparing(Equipment::getDifference).reversed())
                        .collect(Collectors.toList());
            }
            if (show.isEmpty()) {
                eventManager.notifyMessage("没有找到比当前更优秀的装备，默认隐藏属性更低的装备", 1);
                break;
            }
            for (int i = 0; i < show.size(); i++) {
                Equipment equipment = show.get(i);
                Equipment position = hero.getEquips().findByPosition(equipment.getEquipmentPosition());
                int difference = equipment.getDifference();
                eventManager.notifyMessage((i + 1) + ": " + equipment.showDifference(position, hero) + "\t "
                        + "  总评（ " + (difference > 0 ? (ConsoleColors.GREEN_BRIGHT + difference + ConsoleColors.RESET) : (ConsoleColors.RED + difference + ConsoleColors.RESET)) + ")", 1);
            }
            eventManager.notifyMessage("请选择序号 操作对应的装备 输入0 返回", 1);
        }
    }

    private void saleEquipments(HeroWrapper wrapper) {

        eventManager.notifyMessage("是否卖掉当前背包中的所有未穿着的装备  1、全部 2 白色以下 3 蓝色及以下 4 黄色及以下" +
                " 5 紫色及以下 6 红色及以下 7 全部 0 放弃", 1);
        eventManager.notifyPrompt("请选择：");
        int choose = ScannerInput.inputInt(1, 7, 0);
        if (choose == 0) {
            return;
        }

        List<Equipment> equipmentList = wrapper.getWarehouse().getEquipmentList();
        List<Equipment> notUseList = equipmentList.stream()
                .filter(e -> e.getQuality().getId() <= choose)
                .filter(e -> !e.isUsed()).collect(Collectors.toList());

        for (Equipment equipment : notUseList) {
            Coin coin = equipment.sale();
            wrapper.pickUp(null, coin);
        }
        equipmentList.removeAll(notUseList);
    }

    private void saleEggs(HeroWrapper wrapper, boolean filter) {
        List<Egg> eggRest = new ArrayList<>();

        List<Egg> eggList = wrapper.getWarehouse().getEggs();
        for (Egg egg : eggList) {
            // 是否过滤
            if (filter) {
                if (egg.getMonsterTemplate().getQuality() < 4) {
                    Coin coin = egg.sale();
                    wrapper.pickUp(null, coin);
                } else {
                    eggRest.add(egg);
                }
            } else {
                Coin coin = egg.sale();
                wrapper.pickUp(null, coin);
            }
        }
        wrapper.getWarehouse().setEggs(eggRest);
    }

    public void autoFight(HeroWrapper heroWrapper, GameWrapper gameWrapper) {
        LoadGame.save(this.gameWrapper);
        // 先检查装备数量是否大于100 大于100的情况下就要先卖掉一部分
        if (heroWrapper.getWarehouse().getEquipmentList() != null && heroWrapper.getWarehouse().getEquipmentList().size() > 100) {
            eventManager.notifyMessage("装备数超过100，请清理后再进入副本", 1);
            return;
        }

        // 再选择地图
        MapTemplate mapTemplate = MapFactory.selectMap();
        if (mapTemplate == null) {
            return;
        }
        Map map = MapFactory.createMap(mapTemplate);

        // 显示地图的信息 npc + 挑战boss + 挂机
        List<NPC> npcList = map.getNpcList();

        eventManager.notifyMessage("进入地图 ，请选择操作", 1);

        eventManager.notifyMessage("0 退出", 1);
        eventManager.notifyMessage("1 打怪寻宝", 1);
        eventManager.notifyMessage("2 挑战boss", 1);
        int npcIndex = 3;
        if (npcList != null && npcList.size() > 0) {
            for (NPC npc : npcList) {
                eventManager.notifyMessage(npcIndex++ + ":" + npc.getName(), 1);
            }
        }
        eventManager.notifyPrompt("请选择：");
        int choose = ScannerInput.inputInt(0, --npcIndex, 0);
        while (choose != 0) {
            if (choose == 1) {
                findAndFight(heroWrapper, map);
            } else if (choose == 2) {
                try {
                    challengeBoss(heroWrapper, map);
                } catch (Exception exception) {
                    exception.printStackTrace();
                }
            } else {
                NPC npc = npcList.get(choose - 3);
                eventManager.notifyPrompt(npc.getName() + "说:");
                List<String> dialogues = npc.getDialogues();
                Collections.shuffle(dialogues);
                eventManager.notifyMessage("--" + dialogues.get(0), 1);
                // 任务
                mainTaskService.checkTask(npc.getId(),map.getId(),heroWrapper);
            }

            LoadGame.save(gameWrapper);

            eventManager.notifyMessage("------------ 请继续选择 ------------------",1);
            eventManager.notifyMessage("0 退出", 1);
            eventManager.notifyMessage("1 打怪寻宝", 1);
            eventManager.notifyMessage("2 挑战boss", 1);
            npcIndex = 3;
            if (npcList != null && npcList.size() > 0) {
                for (NPC npc : npcList) {
                    eventManager.notifyMessage(npcIndex++ + ":" + npc.getName(), 1);
                }
            }
            eventManager.notifyPrompt("请选择：");
            choose = ScannerInput.inputInt(0, npcIndex, 0);
        }
    }

    private void challengeBoss(HeroWrapper heroWrapper, Map map) throws Exception {

        quit.set(Boolean.FALSE);
        // 输入q退出
        // 单开一个线程检测用户的输入
        CompletableFuture.supplyAsync(
                () -> {
                    try {
                        Scanner input = new Scanner(System.in);
                        eventManager.notifyMessage("输入q 退出", 1);
                        while (true) {
                            try {
                                String choose = input.nextLine();
                                if ("q".equals(choose)) {
                                    quit.set(true);
                                    break;
                                }
                            } catch (Exception exception) {
                                // exception.printStackTrace();
                                break;
                            } finally {
                                input = new Scanner(System.in);
                                input.reset();
                            }
                        }
                        return true;
                    } catch (Exception exception) {
                        exception.printStackTrace();
                        return false;
                    }
                });

        // 主战斗线程池
        ScheduledExecutorService executorService = null;

        // 附属战斗线程池，计算每秒中的各种状态
        ScheduledExecutorService subFightExecutorService = null;

        for (; ; ) {
            Hero hero = heroWrapper.getHero();
            List<Monster> fightPets = heroWrapper.getFightPets();
            List<Character> attacks = new ArrayList<>();
            attacks.add(hero);
            attacks.addAll(fightPets);
            int monsterId;
            for (MapTemplate.BossData bossData : map.getBossList()) {
                List<Monster> monsters = new ArrayList<>();
                monsterId = bossData.getMonsterId();
                Monster monster = MonsterFactory.createMonster(bossData.getMonsterId(), bossData.getLevel(), false);
                monsters.add(monster);

                List<String> teamMembers = bossData.getTeamMembers();
                for (String teamMember : teamMembers) {
                    monster = MonsterFactory.createMonster(Integer.parseInt(teamMember), bossData.getLevel(), false);
                    monsters.add(monster);
                }
                // 初始化线程池
                Boolean result = null;
                CompletableFuture<?> future = null;
                try {
                    executorService = Executors.newScheduledThreadPool(4);
                    // executorService = new ScheduledThreadPoolExecutor(5);
                    subFightExecutorService = Executors.newScheduledThreadPool(2);
                    Battle battle = new Battle(executorService, subFightExecutorService);
                    battle.setFallingGoodsCalculator(new FallingGoodsCalculator());
                    battle.setFallCoinCalculator(new FallingCoinCalculator());
                    // 不关心战斗中的能力增幅
                    battle.setCampA(BeanCopyUtils.deepCopy(attacks));
                    battle.setAttackHero(heroWrapper);
                    battle.setDropList(bossData.getDropList());
                    eventManager.notifyMessage("发起进攻方", 1);
                    for (Character character : battle.getCampA()) {
                        eventManager.notifyMessage(character.toString(), 1);
                    }

                    battle.setCampB(monsters);
                    eventManager.notifyMessage("怪物群", 1);
                    for (Character character : battle.getCampB()) {
                        eventManager.notifyMessage(character.toString(), 1);
                    }
                    timer = new HashedWheelTimer(100, TimeUnit.MILLISECONDS, 256);
                    future = CompletableFuture.supplyAsync(battle::fight);
                    // 5分钟 120秒
                    result = (Boolean) future.get(Constants.TIME_OF_EACH_ROUND, TimeUnit.SECONDS);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (future != null && !future.isCancelled()) {
                        future.cancel(true);
                    }
                    if (executorService != null) {
                        executorService.shutdownNow();
                    }
                    if (subFightExecutorService != null) {
                        subFightExecutorService.shutdownNow();
                    }
                    timer.stop();
                }
                if (result == null) {
                    eventManager.notifyMessage("时间到，平局", 1);
                } else {
                    eventManager.notifyMessage(result ? "挑战成功" : "失败了，继续挑战", 1);
                }
                // 挑战记录
                heroWrapper.writeFightRecords(monsters,result);
                LoadGame.save(gameWrapper);
                if(result == null || !result){
                    break;
                }
            }
            if (quit.get()) {
                break;
            }
        }

    }

    public void findAndFight(HeroWrapper heroWrapper, Map map) {
        // 主战斗线程池
        ScheduledExecutorService executorService = null;

        // 附属战斗线程池，计算每秒中的各种状态
        ScheduledExecutorService subFightExecutorService = null;

        quit.set(Boolean.FALSE);
        // 输入q退出
        // 单开一个线程检测用户的输入
        CompletableFuture.supplyAsync(
                () -> {
                    try {
                        Scanner input = new Scanner(System.in);
                        eventManager.notifyMessage("输入q 退出", 1);
                        while (true) {
                            try {
                                String choose = input.nextLine();
                                if ("q".equals(choose)) {
                                    quit.set(true);
                                    break;
                                }
                            } catch (Exception exception) {
                                // exception.printStackTrace();
                            } finally {
                                input = new Scanner(System.in);
                                input.reset();
                            }
                        }
                        return true;
                    } catch (Exception exception) {
                        exception.printStackTrace();
                        return false;
                    }
                });


        for (; ; ) {
            try {
                // 初始化线程池
                executorService = Executors.newScheduledThreadPool(2);
                subFightExecutorService = Executors.newScheduledThreadPool(2);

                timer = new HashedWheelTimer(100, TimeUnit.MILLISECONDS, 256);
                map.fight(heroWrapper, executorService, subFightExecutorService);
                if (quit.get()) {
                    break;
                }
                LoadGame.save(gameWrapper);
                eventManager.notifyMessage("输入q 退出", 1);
            } catch (Exception exception) {
                exception.printStackTrace();
            } finally {
                if (executorService != null) {
                    executorService.shutdownNow();
                }
                if (subFightExecutorService != null) {
                    subFightExecutorService.shutdownNow();
                }
                timer.stop();
            }
        }
    }
}
